<!DOCTYPE html>
<!-- saved from url=(0044)http://cs.lmu.edu/~ray/notes/aelinterpreter/ -->
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>An Interpreter for Ael</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="./An Interpreter for Ael_files/default.css">
<link rel="stylesheet" type="text/css" href="./An Interpreter for Ael_files/prettify.css">
<link rel="stylesheet" href="./An Interpreter for Ael_files/css">
<script src="./An Interpreter for Ael_files/prettify.js.下载"></script>
<style type="text/css">.MathJax_Hover_Frame {border-radius: .25em; -webkit-border-radius: .25em; -moz-border-radius: .25em; -khtml-border-radius: .25em; box-shadow: 0px 0px 15px #83A; -webkit-box-shadow: 0px 0px 15px #83A; -moz-box-shadow: 0px 0px 15px #83A; -khtml-box-shadow: 0px 0px 15px #83A; border: 1px solid #A6D ! important; display: inline-block; position: absolute}
.MathJax_Menu_Button .MathJax_Hover_Arrow {position: absolute; cursor: pointer; display: inline-block; border: 2px solid #AAA; border-radius: 4px; -webkit-border-radius: 4px; -moz-border-radius: 4px; -khtml-border-radius: 4px; font-family: 'Courier New',Courier; font-size: 9px; color: #F0F0F0}
.MathJax_Menu_Button .MathJax_Hover_Arrow span {display: block; background-color: #AAA; border: 1px solid; border-radius: 3px; line-height: 0; padding: 4px}
.MathJax_Hover_Arrow:hover {color: white!important; border: 2px solid #CCC!important}
.MathJax_Hover_Arrow:hover span {background-color: #CCC!important}
</style><style type="text/css">#MathJax_About {position: fixed; left: 50%; width: auto; text-align: center; border: 3px outset; padding: 1em 2em; background-color: #DDDDDD; color: black; cursor: default; font-family: message-box; font-size: 120%; font-style: normal; text-indent: 0; text-transform: none; line-height: normal; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; z-index: 201; border-radius: 15px; -webkit-border-radius: 15px; -moz-border-radius: 15px; -khtml-border-radius: 15px; box-shadow: 0px 10px 20px #808080; -webkit-box-shadow: 0px 10px 20px #808080; -moz-box-shadow: 0px 10px 20px #808080; -khtml-box-shadow: 0px 10px 20px #808080; filter: progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true')}
#MathJax_About.MathJax_MousePost {outline: none}
.MathJax_Menu {position: absolute; background-color: white; color: black; width: auto; padding: 2px; border: 1px solid #CCCCCC; margin: 0; cursor: default; font: menu; text-align: left; text-indent: 0; text-transform: none; line-height: normal; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; z-index: 201; box-shadow: 0px 10px 20px #808080; -webkit-box-shadow: 0px 10px 20px #808080; -moz-box-shadow: 0px 10px 20px #808080; -khtml-box-shadow: 0px 10px 20px #808080; filter: progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true')}
.MathJax_MenuItem {padding: 2px 2em; background: transparent}
.MathJax_MenuArrow {position: absolute; right: .5em; padding-top: .25em; color: #666666; font-size: .75em}
.MathJax_MenuActive .MathJax_MenuArrow {color: white}
.MathJax_MenuArrow.RTL {left: .5em; right: auto}
.MathJax_MenuCheck {position: absolute; left: .7em}
.MathJax_MenuCheck.RTL {right: .7em; left: auto}
.MathJax_MenuRadioCheck {position: absolute; left: 1em}
.MathJax_MenuRadioCheck.RTL {right: 1em; left: auto}
.MathJax_MenuLabel {padding: 2px 2em 4px 1.33em; font-style: italic}
.MathJax_MenuRule {border-top: 1px solid #CCCCCC; margin: 4px 1px 0px}
.MathJax_MenuDisabled {color: GrayText}
.MathJax_MenuActive {background-color: Highlight; color: HighlightText}
.MathJax_MenuDisabled:focus, .MathJax_MenuLabel:focus {background-color: #E8E8E8}
.MathJax_ContextMenu:focus {outline: none}
.MathJax_ContextMenu .MathJax_MenuItem:focus {outline: none}
#MathJax_AboutClose {top: .2em; right: .2em}
.MathJax_Menu .MathJax_MenuClose {top: -10px; left: -10px}
.MathJax_MenuClose {position: absolute; cursor: pointer; display: inline-block; border: 2px solid #AAA; border-radius: 18px; -webkit-border-radius: 18px; -moz-border-radius: 18px; -khtml-border-radius: 18px; font-family: 'Courier New',Courier; font-size: 24px; color: #F0F0F0}
.MathJax_MenuClose span {display: block; background-color: #AAA; border: 1.5px solid; border-radius: 18px; -webkit-border-radius: 18px; -moz-border-radius: 18px; -khtml-border-radius: 18px; line-height: 0; padding: 8px 0 6px}
.MathJax_MenuClose:hover {color: white!important; border: 2px solid #CCC!important}
.MathJax_MenuClose:hover span {background-color: #CCC!important}
.MathJax_MenuClose:hover:focus {outline: none}
</style><style type="text/css">.MathJax_Preview .MJXf-math {color: inherit!important}
</style><style type="text/css">.MJX_Assistive_MathML {position: absolute!important; top: 0; left: 0; clip: rect(1px, 1px, 1px, 1px); padding: 1px 0 0 0!important; border: 0!important; height: 1px!important; width: 1px!important; overflow: hidden!important; display: block!important; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none}
.MJX_Assistive_MathML.MJX_Assistive_MathML_Block {width: 100%!important}
</style><style type="text/css">#MathJax_Zoom {position: absolute; background-color: #F0F0F0; overflow: auto; display: block; z-index: 301; padding: .5em; border: 1px solid black; margin: 0; font-weight: normal; font-style: normal; text-align: left; text-indent: 0; text-transform: none; line-height: normal; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box; box-shadow: 5px 5px 15px #AAAAAA; -webkit-box-shadow: 5px 5px 15px #AAAAAA; -moz-box-shadow: 5px 5px 15px #AAAAAA; -khtml-box-shadow: 5px 5px 15px #AAAAAA; filter: progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true')}
#MathJax_ZoomOverlay {position: absolute; left: 0; top: 0; z-index: 300; display: inline-block; width: 100%; height: 100%; border: 0; padding: 0; margin: 0; background-color: white; opacity: 0; filter: alpha(opacity=0)}
#MathJax_ZoomFrame {position: relative; display: inline-block; height: 0; width: 0}
#MathJax_ZoomEventTrap {position: absolute; left: 0; top: 0; z-index: 302; display: inline-block; border: 0; padding: 0; margin: 0; background-color: white; opacity: 0; filter: alpha(opacity=0)}
</style><style type="text/css">.MathJax_Preview {color: #888}
#MathJax_Message {position: fixed; left: 1em; bottom: 1.5em; background-color: #E6E6E6; border: 1px solid #959595; margin: 0px; padding: 2px 8px; z-index: 102; color: black; font-size: 80%; width: auto; white-space: nowrap}
#MathJax_MSIE_Frame {position: absolute; top: 0; left: 0; width: 0px; z-index: 101; border: 0px; margin: 0px; padding: 0px}
.MathJax_Error {color: #CC0000; font-style: italic}
</style><style type="text/css">.MJXp-script {font-size: .8em}
.MJXp-right {-webkit-transform-origin: right; -moz-transform-origin: right; -ms-transform-origin: right; -o-transform-origin: right; transform-origin: right}
.MJXp-bold {font-weight: bold}
.MJXp-italic {font-style: italic}
.MJXp-scr {font-family: MathJax_Script,'Times New Roman',Times,STIXGeneral,serif}
.MJXp-frak {font-family: MathJax_Fraktur,'Times New Roman',Times,STIXGeneral,serif}
.MJXp-sf {font-family: MathJax_SansSerif,'Times New Roman',Times,STIXGeneral,serif}
.MJXp-cal {font-family: MathJax_Caligraphic,'Times New Roman',Times,STIXGeneral,serif}
.MJXp-mono {font-family: MathJax_Typewriter,'Times New Roman',Times,STIXGeneral,serif}
.MJXp-largeop {font-size: 150%}
.MJXp-largeop.MJXp-int {vertical-align: -.2em}
.MJXp-math {display: inline-block; line-height: 1.2; text-indent: 0; font-family: 'Times New Roman',Times,STIXGeneral,serif; white-space: nowrap; border-collapse: collapse}
.MJXp-display {display: block; text-align: center; margin: 1em 0}
.MJXp-math span {display: inline-block}
.MJXp-box {display: block!important; text-align: center}
.MJXp-box:after {content: " "}
.MJXp-rule {display: block!important; margin-top: .1em}
.MJXp-char {display: block!important}
.MJXp-mo {margin: 0 .15em}
.MJXp-mfrac {margin: 0 .125em; vertical-align: .25em}
.MJXp-denom {display: inline-table!important; width: 100%}
.MJXp-denom > * {display: table-row!important}
.MJXp-surd {vertical-align: top}
.MJXp-surd > * {display: block!important}
.MJXp-script-box > *  {display: table!important; height: 50%}
.MJXp-script-box > * > * {display: table-cell!important; vertical-align: top}
.MJXp-script-box > *:last-child > * {vertical-align: bottom}
.MJXp-script-box > * > * > * {display: block!important}
.MJXp-mphantom {visibility: hidden}
.MJXp-munderover {display: inline-table!important}
.MJXp-over {display: inline-block!important; text-align: center}
.MJXp-over > * {display: block!important}
.MJXp-munderover > * {display: table-row!important}
.MJXp-mtable {vertical-align: .25em; margin: 0 .125em}
.MJXp-mtable > * {display: inline-table!important; vertical-align: middle}
.MJXp-mtr {display: table-row!important}
.MJXp-mtd {display: table-cell!important; text-align: center; padding: .5em 0 0 .5em}
.MJXp-mtr > .MJXp-mtd:first-child {padding-left: 0}
.MJXp-mtr:first-child > .MJXp-mtd {padding-top: 0}
.MJXp-mlabeledtr {display: table-row!important}
.MJXp-mlabeledtr > .MJXp-mtd:first-child {padding-left: 0}
.MJXp-mlabeledtr:first-child > .MJXp-mtd {padding-top: 0}
.MJXp-merror {background-color: #FFFF88; color: #CC0000; border: 1px solid #CC0000; padding: 1px 3px; font-style: normal; font-size: 90%}
.MJXp-scale0 {-webkit-transform: scaleX(.0); -moz-transform: scaleX(.0); -ms-transform: scaleX(.0); -o-transform: scaleX(.0); transform: scaleX(.0)}
.MJXp-scale1 {-webkit-transform: scaleX(.1); -moz-transform: scaleX(.1); -ms-transform: scaleX(.1); -o-transform: scaleX(.1); transform: scaleX(.1)}
.MJXp-scale2 {-webkit-transform: scaleX(.2); -moz-transform: scaleX(.2); -ms-transform: scaleX(.2); -o-transform: scaleX(.2); transform: scaleX(.2)}
.MJXp-scale3 {-webkit-transform: scaleX(.3); -moz-transform: scaleX(.3); -ms-transform: scaleX(.3); -o-transform: scaleX(.3); transform: scaleX(.3)}
.MJXp-scale4 {-webkit-transform: scaleX(.4); -moz-transform: scaleX(.4); -ms-transform: scaleX(.4); -o-transform: scaleX(.4); transform: scaleX(.4)}
.MJXp-scale5 {-webkit-transform: scaleX(.5); -moz-transform: scaleX(.5); -ms-transform: scaleX(.5); -o-transform: scaleX(.5); transform: scaleX(.5)}
.MJXp-scale6 {-webkit-transform: scaleX(.6); -moz-transform: scaleX(.6); -ms-transform: scaleX(.6); -o-transform: scaleX(.6); transform: scaleX(.6)}
.MJXp-scale7 {-webkit-transform: scaleX(.7); -moz-transform: scaleX(.7); -ms-transform: scaleX(.7); -o-transform: scaleX(.7); transform: scaleX(.7)}
.MJXp-scale8 {-webkit-transform: scaleX(.8); -moz-transform: scaleX(.8); -ms-transform: scaleX(.8); -o-transform: scaleX(.8); transform: scaleX(.8)}
.MJXp-scale9 {-webkit-transform: scaleX(.9); -moz-transform: scaleX(.9); -ms-transform: scaleX(.9); -o-transform: scaleX(.9); transform: scaleX(.9)}
.MathJax_PHTML .noError {vertical-align: ; font-size: 90%; text-align: left; color: black; padding: 1px 3px; border: 1px solid}
</style><style type="text/css">.MathJax_Display {text-align: center; margin: 1em 0em; position: relative; display: block!important; text-indent: 0; max-width: none; max-height: none; min-width: 0; min-height: 0; width: 100%}
.MathJax .merror {background-color: #FFFF88; color: #CC0000; border: 1px solid #CC0000; padding: 1px 3px; font-style: normal; font-size: 90%}
.MathJax .MJX-monospace {font-family: monospace}
.MathJax .MJX-sans-serif {font-family: sans-serif}
#MathJax_Tooltip {background-color: InfoBackground; color: InfoText; border: 1px solid black; box-shadow: 2px 2px 5px #AAAAAA; -webkit-box-shadow: 2px 2px 5px #AAAAAA; -moz-box-shadow: 2px 2px 5px #AAAAAA; -khtml-box-shadow: 2px 2px 5px #AAAAAA; filter: progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true'); padding: 3px 4px; z-index: 401; position: absolute; left: 0; top: 0; width: auto; height: auto; display: none}
.MathJax {display: inline; font-style: normal; font-weight: normal; line-height: normal; font-size: 100%; font-size-adjust: none; text-indent: 0; text-align: left; text-transform: none; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0; min-height: 0; border: 0; padding: 0; margin: 0}
.MathJax:focus, body :focus .MathJax {display: inline-table}
.MathJax.MathJax_FullWidth {text-align: center; display: table-cell!important; width: 10000em!important}
.MathJax img, .MathJax nobr, .MathJax a {border: 0; padding: 0; margin: 0; max-width: none; max-height: none; min-width: 0; min-height: 0; vertical-align: 0; line-height: normal; text-decoration: none}
img.MathJax_strut {border: 0!important; padding: 0!important; margin: 0!important; vertical-align: 0!important}
.MathJax span {display: inline; position: static; border: 0; padding: 0; margin: 0; vertical-align: 0; line-height: normal; text-decoration: none}
.MathJax nobr {white-space: nowrap!important}
.MathJax img {display: inline!important; float: none!important}
.MathJax * {transition: none; -webkit-transition: none; -moz-transition: none; -ms-transition: none; -o-transition: none}
.MathJax_Processing {visibility: hidden; position: fixed; width: 0; height: 0; overflow: hidden}
.MathJax_Processed {display: none!important}
.MathJax_ExBox {display: block!important; overflow: hidden; width: 1px; height: 60ex; min-height: 0; max-height: none}
.MathJax .MathJax_EmBox {display: block!important; overflow: hidden; width: 1px; height: 60em; min-height: 0; max-height: none}
.MathJax_LineBox {display: table!important}
.MathJax_LineBox span {display: table-cell!important; width: 10000em!important; min-width: 0; max-width: none; padding: 0; border: 0; margin: 0}
.MathJax .MathJax_HitBox {cursor: text; background: white; opacity: 0; filter: alpha(opacity=0)}
.MathJax .MathJax_HitBox * {filter: none; opacity: 1; background: transparent}
#MathJax_Tooltip * {filter: none; opacity: 1; background: transparent}
@font-face {font-family: MathJax_Main; src: url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/woff/MathJax_Main-Regular.woff?V=2.7.1') format('woff'), url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/otf/MathJax_Main-Regular.otf?V=2.7.1') format('opentype')}
@font-face {font-family: MathJax_Main-bold; src: url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/woff/MathJax_Main-Bold.woff?V=2.7.1') format('woff'), url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/otf/MathJax_Main-Bold.otf?V=2.7.1') format('opentype')}
@font-face {font-family: MathJax_Main-italic; src: url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/woff/MathJax_Main-Italic.woff?V=2.7.1') format('woff'), url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/otf/MathJax_Main-Italic.otf?V=2.7.1') format('opentype')}
@font-face {font-family: MathJax_Math-italic; src: url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/woff/MathJax_Math-Italic.woff?V=2.7.1') format('woff'), url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/otf/MathJax_Math-Italic.otf?V=2.7.1') format('opentype')}
@font-face {font-family: MathJax_Caligraphic; src: url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/woff/MathJax_Caligraphic-Regular.woff?V=2.7.1') format('woff'), url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/otf/MathJax_Caligraphic-Regular.otf?V=2.7.1') format('opentype')}
@font-face {font-family: MathJax_Size1; src: url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/woff/MathJax_Size1-Regular.woff?V=2.7.1') format('woff'), url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/otf/MathJax_Size1-Regular.otf?V=2.7.1') format('opentype')}
@font-face {font-family: MathJax_Size2; src: url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/woff/MathJax_Size2-Regular.woff?V=2.7.1') format('woff'), url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/otf/MathJax_Size2-Regular.otf?V=2.7.1') format('opentype')}
@font-face {font-family: MathJax_Size3; src: url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/woff/MathJax_Size3-Regular.woff?V=2.7.1') format('woff'), url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/otf/MathJax_Size3-Regular.otf?V=2.7.1') format('opentype')}
@font-face {font-family: MathJax_Size4; src: url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/woff/MathJax_Size4-Regular.woff?V=2.7.1') format('woff'), url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/otf/MathJax_Size4-Regular.otf?V=2.7.1') format('opentype')}
.MathJax .noError {vertical-align: ; font-size: 90%; text-align: left; color: black; padding: 1px 3px; border: 1px solid}
</style></head>
  <body class="coursenotes"><div style="visibility: hidden; overflow: hidden; position: absolute; top: 0px; height: 1px; width: auto; padding: 0px; border: 0px; margin: 0px; text-align: left; text-indent: 0px; text-transform: none; line-height: normal; letter-spacing: normal; word-spacing: normal;"><div id="MathJax_Hidden"></div></div><div id="MathJax_Message" style="display: none;"></div>
    <script>onload = function () {prettyPrint();}</script>
    <div class="container">
      <div class="innercontent">
        <h1>An Interpreter for Ael</h1>

<script type="text/x-mathjax-config;executed=true">MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$']], displaymath: [['$$','$$']]}});</script><script src="./An Interpreter for Ael_files/MathJax.js.下载"></script>
<div class="abstract">Time to write an interpreter.</div><div id="contents"><div>CONTENTS</div><div>Organizing an Interpreter • Writing an Interpreter with Ohm • A Few Notes on Ohm</div></div>

<h2>Organizing an Interpreter</h2>

<p>An interpreter <em>runs</em> code.</p>

<p>If you have machine code, your CPU is your interpreter. Sometimes people design <b>abstract machines</b> with very low-level code with simple, precise, “instructions” that, while more powerful than processor instructions, are super simple to write interpreters for.</p>

<p>But what about writing interpreters for higher-level languages? One way is to:</p>
<ol>
<li>write a front-end to produce the AST, then
</li><li>write a back-end to produce (abstract or real) machine code from the AST, then
</li><li>interpret the low-level code.
</li></ol>

<p>You can also just interpret the AST directly. in other words:</p>
<ol>
<li>write a front-end to produce the AST, then
</li><li>interpret the AST.
</li></ol>

<p>Or, we can use <a href="https://github.com/harc/ohm">Ohm</a>, which provides a way to generate the (concrete) parse tree that we can interpret directly.</p>

<h2>Writing an Interpreter with Ohm</h2>

<p>Here is an complete, quick-and-dirty interpreter for Ael, written with Ohm:</p>

<div class="filename"><span>ael-interpreter.js</span></div><pre class="prettyprint"><span class="com">// An interpreter for Ael.</span><span class="pln"><br></span><span class="com">//</span><span class="pln"><br></span><span class="com">// Example usage:</span><span class="pln"><br></span><span class="com">//</span><span class="pln"><br></span><span class="com">// &nbsp; $ node ael.js '8 + (7 / 2)'</span><span class="pln"><br></span><span class="com">// &nbsp; 11.5</span><span class="pln"><br><br></span><span class="kwd">const</span><span class="pln"> ohm </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">require</span><span class="pun">(</span><span class="str">'ohm-js'</span><span class="pun">);</span><span class="pln"><br><br></span><span class="kwd">const</span><span class="pln"> aelGrammar </span><span class="pun">=</span><span class="pln"> ohm</span><span class="pun">.</span><span class="pln">grammar</span><span class="pun">(</span><span class="str">`Ael {<br>&nbsp; Exp &nbsp; &nbsp; = Exp "+" Term &nbsp; &nbsp; --plus<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Exp "-" Term &nbsp; &nbsp; --minus<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Term<br>&nbsp; Term &nbsp; &nbsp;= Term "*" Factor &nbsp;--times<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Term "/" Factor &nbsp;--divide<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Factor<br>&nbsp; Factor &nbsp;= "-" Primary &nbsp; &nbsp; &nbsp;--negate<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Primary<br>&nbsp; Primary = "(" Exp ")" &nbsp; &nbsp; &nbsp;--parens<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | number<br>&nbsp; number &nbsp;= digit+<br>&nbsp; space &nbsp;:= " " | "\t"<br>}`</span><span class="pun">);</span><span class="pln"><br><br></span><span class="com">// This language is so simple, we don't need an AST.</span><span class="pln"><br></span><span class="kwd">const</span><span class="pln"> semantics </span><span class="pun">=</span><span class="pln"> aelGrammar</span><span class="pun">.</span><span class="pln">createSemantics</span><span class="pun">().</span><span class="pln">addOperation</span><span class="pun">(</span><span class="str">'eval'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; </span><span class="typ">Exp_plus</span><span class="pun">(</span><span class="pln">e</span><span class="pun">,</span><span class="pln"> _</span><span class="pun">,</span><span class="pln"> t</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> e</span><span class="pun">.</span><span class="kwd">eval</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> t</span><span class="pun">.</span><span class="kwd">eval</span><span class="pun">();</span><span class="pln"> </span><span class="pun">},</span><span class="pln"><br>&nbsp; </span><span class="typ">Exp_minus</span><span class="pun">(</span><span class="pln">e</span><span class="pun">,</span><span class="pln"> _</span><span class="pun">,</span><span class="pln"> t</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> e</span><span class="pun">.</span><span class="kwd">eval</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> t</span><span class="pun">.</span><span class="kwd">eval</span><span class="pun">();</span><span class="pln"> </span><span class="pun">},</span><span class="pln"><br>&nbsp; </span><span class="typ">Term_times</span><span class="pun">(</span><span class="pln">t</span><span class="pun">,</span><span class="pln"> _</span><span class="pun">,</span><span class="pln"> f</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> t</span><span class="pun">.</span><span class="kwd">eval</span><span class="pun">()</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> f</span><span class="pun">.</span><span class="kwd">eval</span><span class="pun">();</span><span class="pln"> </span><span class="pun">},</span><span class="pln"><br>&nbsp; </span><span class="typ">Term_divide</span><span class="pun">(</span><span class="pln">t</span><span class="pun">,</span><span class="pln"> _</span><span class="pun">,</span><span class="pln"> f</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> t</span><span class="pun">.</span><span class="kwd">eval</span><span class="pun">()</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> f</span><span class="pun">.</span><span class="kwd">eval</span><span class="pun">();</span><span class="pln"> </span><span class="pun">},</span><span class="pln"><br>&nbsp; </span><span class="typ">Factor_negate</span><span class="pun">(</span><span class="pln">_</span><span class="pun">,</span><span class="pln"> p</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">-</span><span class="pln">p</span><span class="pun">.</span><span class="kwd">eval</span><span class="pun">();</span><span class="pln"> </span><span class="pun">},</span><span class="pln"><br>&nbsp; </span><span class="typ">Primary_parens</span><span class="pun">(</span><span class="pln">_1</span><span class="pun">,</span><span class="pln"> e</span><span class="pun">,</span><span class="pln"> _2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> e</span><span class="pun">.</span><span class="kwd">eval</span><span class="pun">();</span><span class="pln"> </span><span class="pun">},</span><span class="pln"><br>&nbsp; number</span><span class="pun">(</span><span class="pln">chars</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">+</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">sourceString</span><span class="pun">;</span><span class="pln"> </span><span class="pun">},</span><span class="pln"><br></span><span class="pun">});</span><span class="pln"><br><br></span><span class="kwd">const</span><span class="pln"> match </span><span class="pun">=</span><span class="pln"> aelGrammar</span><span class="pun">.</span><span class="pln">match</span><span class="pun">(</span><span class="pln">process</span><span class="pun">.</span><span class="pln">argv</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]);</span><span class="pln"><br></span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">match</span><span class="pun">.</span><span class="pln">succeeded</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">semantics</span><span class="pun">(</span><span class="pln">match</span><span class="pun">).</span><span class="kwd">eval</span><span class="pun">());</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span class="pun">.</span><span class="pln">error</span><span class="pun">(</span><span class="pln">match</span><span class="pun">.</span><span class="pln">message</span><span class="pun">);</span><span class="pln"><br>&nbsp; process</span><span class="pun">.</span><span class="pln">exitCode </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"><br></span><span class="pun">}</span></pre>
<p>And here are some sample runs:</p>

<pre class="console">$ <kbd>node ael-interpreter.js '8 *    (22   - 3) / 4'</kbd>
38
$ <kbd>node ael-interpreter.js '8 * (22 ^  - 3) / 4'</kbd>
Line 1, col 9:
&gt; 1 | 8 * (22 ^  - 3) / 4
              ^
Expected ")"
$ <kbd>node ael-interpreter.js '8 ('</kbd>
Line 1, col 3:
&gt; 1 | 8 (
        ^
Expected end of input
</pre>

<p>We’ll go over this interpreter in great detail in class. But first, a few notes on Ohm. These notes on Ohm are <em>not</em> intended to be a substitute for you reading <a href="https://github.com/harc/ohm/blob/master/README.md">all about Ohm</a> on your own, because we’re going to use it to build big languages later on.</p>

<h2>A Few Notes on Ohm</h2>

<p>Ohm is a library for building parsers, interpreters, compilers, and more. With it you can quickly generate parsers for languages specified with PEGs. There are a few basics that are good to know:</p>

<ol class="spaced">

<li>Install from npm, of course: <code>npm install ohm-js</code>

</li><li>In your program, obtain the <code>ohm</code> object via <code>const ohm = require('ohm-js');</code>

</li><li>Write grammars as you would a regular PEG, but with a few differences (like <code>|</code> for <code>/</code> and <code>=</code> for <code>←</code>). Unlike regular PEGs, Ohm rules can be left-recursive. In addition, Ohm allows some fancy stuff, like parameterized rules and grammar inheritance. Details are in the <a href="https://github.com/harc/ohm/blob/master/doc/syntax-reference.md">syntax reference</a>, which you need to eventually read. But as you may be impatient, here are the Ohm parsing expressions:
  <table>
  <tbody><tr><th>Expression</th><th>Description
  </th></tr><tr><td><code>"</code>...<code>"</code></td><td>A literal string. Allows the usual escape chars <code>\'</code>, <code>\"</code>, <code>\b</code>, <code>\n</code>, <code>\r</code>, <code>\t</code>, <code>\f</code>, <code>\\</code>, <code>\x</code><span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-1-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-1" style="width: 1.449em; display: inline-block;"><span style="display: inline-block; position: relative; width: 1.16em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.401em 1001.16em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-2"><span class="mi" id="MathJax-Span-3" style="font-family: MathJax_Math-italic;">h</span><span class="mi" id="MathJax-Span-4" style="font-family: MathJax_Math-italic;">h</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 1.003em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>h</mi><mi>h</mi></math></span></span><script type="math/tex" id="MathJax-Element-1">hh</script>, <code>\u</code><span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-2-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-5" style="width: 2.847em; display: inline-block;"><span style="display: inline-block; position: relative; width: 2.317em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.401em 1002.32em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-6"><span class="mi" id="MathJax-Span-7" style="font-family: MathJax_Math-italic;">h</span><span class="mi" id="MathJax-Span-8" style="font-family: MathJax_Math-italic;">h</span><span class="mi" id="MathJax-Span-9" style="font-family: MathJax_Math-italic;">h</span><span class="mi" id="MathJax-Span-10" style="font-family: MathJax_Math-italic;">h</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 1.003em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>h</mi><mi>h</mi><mi>h</mi><mi>h</mi></math></span></span><script type="math/tex" id="MathJax-Element-2">hhhh</script>.
  </td></tr><tr><td><span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-3-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-11" style="width: 5.21em; display: inline-block;"><span style="display: inline-block; position: relative; width: 4.245em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.401em 1004.2em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-12"><span class="mi" id="MathJax-Span-13" style="font-family: MathJax_Math-italic;">r</span><span class="mi" id="MathJax-Span-14" style="font-family: MathJax_Math-italic;">u</span><span class="mi" id="MathJax-Span-15" style="font-family: MathJax_Math-italic;">l</span><span class="mi" id="MathJax-Span-16" style="font-family: MathJax_Math-italic;">e</span><span class="mi" id="MathJax-Span-17" style="font-family: MathJax_Math-italic;">n</span><span class="mi" id="MathJax-Span-18" style="font-family: MathJax_Math-italic;">a</span><span class="mi" id="MathJax-Span-19" style="font-family: MathJax_Math-italic;">m</span><span class="mi" id="MathJax-Span-20" style="font-family: MathJax_Math-italic;">e</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 1.003em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>r</mi><mi>u</mi><mi>l</mi><mi>e</mi><mi>n</mi><mi>a</mi><mi>m</mi><mi>e</mi></math></span></span><script type="math/tex" id="MathJax-Element-3">rulename</script></td><td>Just a rule.
  </td></tr><tr><td><span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-4-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-21" style="width: 5.21em; display: inline-block;"><span style="display: inline-block; position: relative; width: 4.245em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.401em 1004.2em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-22"><span class="mi" id="MathJax-Span-23" style="font-family: MathJax_Math-italic;">r</span><span class="mi" id="MathJax-Span-24" style="font-family: MathJax_Math-italic;">u</span><span class="mi" id="MathJax-Span-25" style="font-family: MathJax_Math-italic;">l</span><span class="mi" id="MathJax-Span-26" style="font-family: MathJax_Math-italic;">e</span><span class="mi" id="MathJax-Span-27" style="font-family: MathJax_Math-italic;">n</span><span class="mi" id="MathJax-Span-28" style="font-family: MathJax_Math-italic;">a</span><span class="mi" id="MathJax-Span-29" style="font-family: MathJax_Math-italic;">m</span><span class="mi" id="MathJax-Span-30" style="font-family: MathJax_Math-italic;">e</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 1.003em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>r</mi><mi>u</mi><mi>l</mi><mi>e</mi><mi>n</mi><mi>a</mi><mi>m</mi><mi>e</mi></math></span></span><script type="math/tex" id="MathJax-Element-4">rulename</script><code>&lt;</code><span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-5-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-31" style="width: 4.149em; display: inline-block;"><span style="display: inline-block; position: relative; width: 3.378em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1003.33em 2.558em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-32"><span class="mi" id="MathJax-Span-33" style="font-family: MathJax_Math-italic;">p</span><span class="mi" id="MathJax-Span-34" style="font-family: MathJax_Math-italic;">a</span><span class="mi" id="MathJax-Span-35" style="font-family: MathJax_Math-italic;">r</span><span class="mi" id="MathJax-Span-36" style="font-family: MathJax_Math-italic;">a</span><span class="mi" id="MathJax-Span-37" style="font-family: MathJax_Math-italic;">m</span><span class="mi" id="MathJax-Span-38" style="font-family: MathJax_Math-italic;">s</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.291em; border-left: 0px solid; width: 0px; height: 0.885em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>p</mi><mi>a</mi><mi>r</mi><mi>a</mi><mi>m</mi><mi>s</mi></math></span></span><script type="math/tex" id="MathJax-Element-5">params</script><code>&gt;</code></td><td>A rule with parameters.
  </td></tr><tr><td><span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-6-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-39" style="width: 0.629em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.485em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.44em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-40"><span class="mi" id="MathJax-Span-41" style="font-family: MathJax_Math-italic;">e</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 0.65em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>e</mi></math></span></span><script type="math/tex" id="MathJax-Element-6">e</script><code>*</code></td><td><span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-7-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-42" style="width: 0.629em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.485em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.44em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-43"><span class="mi" id="MathJax-Span-44" style="font-family: MathJax_Math-italic;">e</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 0.65em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>e</mi></math></span></span><script type="math/tex" id="MathJax-Element-7">e</script>, zero or more times.
  </td></tr><tr><td><span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-8-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-45" style="width: 0.629em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.485em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.44em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-46"><span class="mi" id="MathJax-Span-47" style="font-family: MathJax_Math-italic;">e</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 0.65em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>e</mi></math></span></span><script type="math/tex" id="MathJax-Element-8">e</script><code>+</code></td><td><span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-9-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-48" style="width: 0.629em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.485em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.44em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-49"><span class="mi" id="MathJax-Span-50" style="font-family: MathJax_Math-italic;">e</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 0.65em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>e</mi></math></span></span><script type="math/tex" id="MathJax-Element-9">e</script>, one or more times.
  </td></tr><tr><td><span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-10-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-51" style="width: 0.629em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.485em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.44em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-52"><span class="mi" id="MathJax-Span-53" style="font-family: MathJax_Math-italic;">e</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 0.65em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>e</mi></math></span></span><script type="math/tex" id="MathJax-Element-10">e</script><code>?</code></td><td><span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-11-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-54" style="width: 0.629em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.485em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.44em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-55"><span class="mi" id="MathJax-Span-56" style="font-family: MathJax_Math-italic;">e</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 0.65em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>e</mi></math></span></span><script type="math/tex" id="MathJax-Element-11">e</script>, zero or one times.
  </td></tr><tr><td><span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-12-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mspace width=&quot;thickmathspace&quot; /&gt;&lt;msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-57" style="width: 2.606em; display: inline-block;"><span style="display: inline-block; position: relative; width: 2.124em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1002.12em 2.51em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-58"><span class="msubsup" id="MathJax-Span-59"><span style="display: inline-block; position: relative; width: 0.919em; height: 0px;"><span style="position: absolute; clip: rect(3.426em 1000.44em 4.149em -999.998em); top: -4em; left: 0em;"><span class="mi" id="MathJax-Span-60" style="font-family: MathJax_Math-italic;">e</span><span style="display: inline-block; width: 0px; height: 4.004em;"></span></span><span style="position: absolute; top: -3.855em; left: 0.485em;"><span class="mn" id="MathJax-Span-61" style="font-size: 70.7%; font-family: MathJax_Main;">1</span><span style="display: inline-block; width: 0px; height: 4.004em;"></span></span></span></span><span class="mspace" id="MathJax-Span-62" style="height: 0em; vertical-align: 0em; width: 0.292em; display: inline-block; overflow: hidden;"></span><span class="msubsup" id="MathJax-Span-63"><span style="display: inline-block; position: relative; width: 0.919em; height: 0px;"><span style="position: absolute; clip: rect(3.426em 1000.44em 4.149em -999.998em); top: -4em; left: 0em;"><span class="mi" id="MathJax-Span-64" style="font-family: MathJax_Math-italic;">e</span><span style="display: inline-block; width: 0px; height: 4.004em;"></span></span><span style="position: absolute; top: -3.855em; left: 0.485em;"><span class="mn" id="MathJax-Span-65" style="font-size: 70.7%; font-family: MathJax_Main;">2</span><span style="display: inline-block; width: 0px; height: 4.004em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.232em; border-left: 0px solid; width: 0px; height: 0.826em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>e</mi><mn>1</mn></msub><mspace width="thickmathspace"></mspace><msub><mi>e</mi><mn>2</mn></msub></math></span></span><script type="math/tex" id="MathJax-Element-12">e_1\;e_2</script></td><td>Match <span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-13-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-66" style="width: 1.111em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.919em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.92em 2.51em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-67"><span class="msubsup" id="MathJax-Span-68"><span style="display: inline-block; position: relative; width: 0.919em; height: 0px;"><span style="position: absolute; clip: rect(3.426em 1000.44em 4.149em -999.998em); top: -4em; left: 0em;"><span class="mi" id="MathJax-Span-69" style="font-family: MathJax_Math-italic;">e</span><span style="display: inline-block; width: 0px; height: 4.004em;"></span></span><span style="position: absolute; top: -3.855em; left: 0.485em;"><span class="mn" id="MathJax-Span-70" style="font-size: 70.7%; font-family: MathJax_Main;">1</span><span style="display: inline-block; width: 0px; height: 4.004em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.232em; border-left: 0px solid; width: 0px; height: 0.826em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>e</mi><mn>1</mn></msub></math></span></span><script type="math/tex" id="MathJax-Element-13">e_1</script> then match <span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-14-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-71" style="width: 1.111em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.919em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.92em 2.51em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-72"><span class="msubsup" id="MathJax-Span-73"><span style="display: inline-block; position: relative; width: 0.919em; height: 0px;"><span style="position: absolute; clip: rect(3.426em 1000.44em 4.149em -999.998em); top: -4em; left: 0em;"><span class="mi" id="MathJax-Span-74" style="font-family: MathJax_Math-italic;">e</span><span style="display: inline-block; width: 0px; height: 4.004em;"></span></span><span style="position: absolute; top: -3.855em; left: 0.485em;"><span class="mn" id="MathJax-Span-75" style="font-size: 70.7%; font-family: MathJax_Main;">2</span><span style="display: inline-block; width: 0px; height: 4.004em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.232em; border-left: 0px solid; width: 0px; height: 0.826em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>e</mi><mn>2</mn></msub></math></span></span><script type="math/tex" id="MathJax-Element-14">e_2</script>.
  </td></tr><tr><td><span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-15-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mspace width=&quot;thickmathspace&quot; /&gt;&lt;mrow class=&quot;MJX-TeXAtom-ORD&quot;&gt;&lt;mo stretchy=&quot;false&quot;&gt;|&lt;/mo&gt;&lt;/mrow&gt;&lt;mspace width=&quot;thickmathspace&quot; /&gt;&lt;msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-76" style="width: 3.329em; display: inline-block;"><span style="display: inline-block; position: relative; width: 2.703em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.352em 1002.7em 2.654em -999.998em); top: -2.264em; left: 0em;"><span class="mrow" id="MathJax-Span-77"><span class="msubsup" id="MathJax-Span-78"><span style="display: inline-block; position: relative; width: 0.919em; height: 0px;"><span style="position: absolute; clip: rect(3.426em 1000.44em 4.149em -999.998em); top: -4em; left: 0em;"><span class="mi" id="MathJax-Span-79" style="font-family: MathJax_Math-italic;">e</span><span style="display: inline-block; width: 0px; height: 4.004em;"></span></span><span style="position: absolute; top: -3.855em; left: 0.485em;"><span class="mn" id="MathJax-Span-80" style="font-size: 70.7%; font-family: MathJax_Main;">1</span><span style="display: inline-block; width: 0px; height: 4.004em;"></span></span></span></span><span class="mspace" id="MathJax-Span-81" style="height: 0em; vertical-align: 0em; width: 0.292em; display: inline-block; overflow: hidden;"></span><span class="texatom" id="MathJax-Span-82"><span class="mrow" id="MathJax-Span-83"><span class="mo" id="MathJax-Span-84" style="font-family: MathJax_Main;">|</span></span></span><span class="mspace" id="MathJax-Span-85" style="height: 0em; vertical-align: 0em; width: 0.292em; display: inline-block; overflow: hidden;"></span><span class="msubsup" id="MathJax-Span-86"><span style="display: inline-block; position: relative; width: 0.919em; height: 0px;"><span style="position: absolute; clip: rect(3.426em 1000.44em 4.149em -999.998em); top: -4em; left: 0em;"><span class="mi" id="MathJax-Span-87" style="font-family: MathJax_Math-italic;">e</span><span style="display: inline-block; width: 0px; height: 4.004em;"></span></span><span style="position: absolute; top: -3.855em; left: 0.485em;"><span class="mn" id="MathJax-Span-88" style="font-size: 70.7%; font-family: MathJax_Main;">2</span><span style="display: inline-block; width: 0px; height: 4.004em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.269em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.35em; border-left: 0px solid; width: 0px; height: 1.356em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>e</mi><mn>1</mn></msub><mspace width="thickmathspace"></mspace><mrow class="MJX-TeXAtom-ORD"><mo stretchy="false">|</mo></mrow><mspace width="thickmathspace"></mspace><msub><mi>e</mi><mn>2</mn></msub></math></span></span><script type="math/tex" id="MathJax-Element-15">e_1\;|\;e_2</script></td><td>If <span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-16-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-89" style="width: 1.111em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.919em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.92em 2.51em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-90"><span class="msubsup" id="MathJax-Span-91"><span style="display: inline-block; position: relative; width: 0.919em; height: 0px;"><span style="position: absolute; clip: rect(3.426em 1000.44em 4.149em -999.998em); top: -4em; left: 0em;"><span class="mi" id="MathJax-Span-92" style="font-family: MathJax_Math-italic;">e</span><span style="display: inline-block; width: 0px; height: 4.004em;"></span></span><span style="position: absolute; top: -3.855em; left: 0.485em;"><span class="mn" id="MathJax-Span-93" style="font-size: 70.7%; font-family: MathJax_Main;">1</span><span style="display: inline-block; width: 0px; height: 4.004em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.232em; border-left: 0px solid; width: 0px; height: 0.826em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>e</mi><mn>1</mn></msub></math></span></span><script type="math/tex" id="MathJax-Element-16">e_1</script> matches, great. Otherwise try to match <span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-17-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-94" style="width: 1.111em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.919em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.92em 2.51em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-95"><span class="msubsup" id="MathJax-Span-96"><span style="display: inline-block; position: relative; width: 0.919em; height: 0px;"><span style="position: absolute; clip: rect(3.426em 1000.44em 4.149em -999.998em); top: -4em; left: 0em;"><span class="mi" id="MathJax-Span-97" style="font-family: MathJax_Math-italic;">e</span><span style="display: inline-block; width: 0px; height: 4.004em;"></span></span><span style="position: absolute; top: -3.855em; left: 0.485em;"><span class="mn" id="MathJax-Span-98" style="font-size: 70.7%; font-family: MathJax_Main;">2</span><span style="display: inline-block; width: 0px; height: 4.004em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.232em; border-left: 0px solid; width: 0px; height: 0.826em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mi>e</mi><mn>2</mn></msub></math></span></span><script type="math/tex" id="MathJax-Element-17">e_2</script>.
  </td></tr><tr><td><code>&amp;</code><span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-18-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-99" style="width: 0.629em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.485em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.44em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-100"><span class="mi" id="MathJax-Span-101" style="font-family: MathJax_Math-italic;">e</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 0.65em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>e</mi></math></span></span><script type="math/tex" id="MathJax-Element-18">e</script></td><td>Match <span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-19-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-102" style="width: 0.629em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.485em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.44em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-103"><span class="mi" id="MathJax-Span-104" style="font-family: MathJax_Math-italic;">e</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 0.65em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>e</mi></math></span></span><script type="math/tex" id="MathJax-Element-19">e</script> without consuming it (lookahead).
  </td></tr><tr><td><code>~</code><span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-20-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-105" style="width: 0.629em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.485em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.44em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-106"><span class="mi" id="MathJax-Span-107" style="font-family: MathJax_Math-italic;">e</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 0.65em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>e</mi></math></span></span><script type="math/tex" id="MathJax-Element-20">e</script></td><td>Succeed if <span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-21-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-108" style="width: 0.629em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.485em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.44em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-109"><span class="mi" id="MathJax-Span-110" style="font-family: MathJax_Math-italic;">e</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 0.65em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>e</mi></math></span></span><script type="math/tex" id="MathJax-Element-21">e</script> doesn’t match, without consuming anything (negative lookahead).
  </td></tr><tr><td><code>#</code><span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-22-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-111" style="width: 0.629em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.485em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.44em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-112"><span class="mi" id="MathJax-Span-113" style="font-family: MathJax_Math-italic;">e</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 0.65em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>e</mi></math></span></span><script type="math/tex" id="MathJax-Element-22">e</script></td><td>Lexify a syntactic rule.
  </td></tr></tbody></table>

</li><li>Note how <b>lexical rules</b> always start with lower case letters and <b>syntax rules</b> start with uppercase letters. Syntax rules allow tokens from the class <code>space</code> to be implicitly interspersed with other tokens.

</li><li>There are several built-in rules:
  <ul class="compressed">
  <li><code>any = </code><em>any char at all</em>
  </li><li><code>end = </code><em>the end of the input</em>
  </li><li><code>space = " " | "\x09".."\x0d" | "\ufeff" | </code><em>any char from Unicode category Zs</em>
  </li><li><code>digit = "0".."9"</code>
  </li><li><code>lower = </code><em>any char from Unicode category Ll</em>
  </li><li><code>upper = </code><em>any char from Unicode category Lu</em>
  </li><li><code>unicodeLtmo = </code><em>any char from Unicode category Lt, Lm, or Lo</em>
  </li><li><code>letter = lower | upper | unicodeLtmo</code>
  </li><li><code>alnum = letter | digit</code>
  </li><li><code>hexDigit = digit | "A".."F" | "a".."f"</code>
  </li><li><code>caseInsensitive&lt;t&gt; = </code><em>any case insensitve version of t</em>
  </li><li><code>emptyListOf&lt;elem, sep&gt; = /* nothing */</code>
  </li><li><code>nonemptyListOf&lt;elem, sep&gt; = elem (sep elem)*</code>
  </li><li><code>listOf&lt;elem, sep&gt; = nonemptyListOf&lt;elem, sep&gt; | emptyListOf&lt;elem, sep&gt;</code>
  </li><li><code>EmptyListOf&lt;elem, sep&gt; = /* nothing */</code>
  </li><li><code>NonemptyListOf&lt;elem, sep&gt; = elem (sep elem)*</code>
  </li><li><code>ListOf&lt;elem, sep&gt; = NonemptyListOf&lt;elem, sep&gt; | EmptyListOf&lt;elem, sep&gt;</code>
  </li></ul>

</li><li>All alternatives for a rule must have the same arity. But there is a cool short-hand to make it look like alternatives with different arities exist. For example:
<pre class="prettyprint"><span class="typ">Exp</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Exp</span><span class="pln"> </span><span class="str">"+"</span><span class="pln"> </span><span class="typ">Term</span><span class="pln"> &nbsp;</span><span class="pun">--</span><span class="pln">plus<br>&nbsp; &nbsp; </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Exp</span><span class="pln"> </span><span class="str">"-"</span><span class="pln"> </span><span class="typ">Term</span><span class="pln"> &nbsp;</span><span class="pun">--</span><span class="pln">minus<br>&nbsp; &nbsp; </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Term</span></pre>
<p>is an abbreviation for:</p>
<pre class="prettyprint"><span class="typ">Exp</span><span class="pln"> &nbsp; &nbsp; &nbsp; </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Exp_plus</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Exp_minus</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Term</span><span class="pln"><br></span><span class="typ">Exp_plus</span><span class="pln"> &nbsp;</span><span class="pun">=</span><span class="pln"> </span><span class="typ">Exp</span><span class="pln"> </span><span class="str">"+"</span><span class="pln"> </span><span class="typ">Term</span><span class="pln"><br></span><span class="typ">Exp_minus</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Exp</span><span class="pln"> </span><span class="str">"-"</span><span class="pln"> </span><span class="typ">Term</span></pre>

</li><li>Grammars can inherit from other grammars. When inheriting, use:
  <ul class="compressed">
  <li><code>=</code> to add a new rule
  </li><li><code>:=</code> to replace the rule from the supergrammar
  </li><li><code>+=</code> to add an alternative to the rule from the supergrammar
  </li></ul>

</li><li>Given a grammar <span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-23-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-114" style="width: 0.629em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.485em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.49em 2.558em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-115"><span class="mi" id="MathJax-Span-116" style="font-family: MathJax_Math-italic;">g<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.002em;"></span></span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.291em; border-left: 0px solid; width: 0px; height: 0.885em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>g</mi></math></span></span><script type="math/tex" id="MathJax-Element-23">g</script> and source code <span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-24-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-117" style="width: 0.533em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.436em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.44em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-118"><span class="mi" id="MathJax-Span-119" style="font-family: MathJax_Math-italic;">c</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 0.65em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>c</mi></math></span></span><script type="math/tex" id="MathJax-Element-24">c</script>, <span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-25-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-120" style="width: 0.629em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.485em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.49em 2.558em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-121"><span class="mi" id="MathJax-Span-122" style="font-family: MathJax_Math-italic;">g<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.002em;"></span></span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.291em; border-left: 0px solid; width: 0px; height: 0.885em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>g</mi></math></span></span><script type="math/tex" id="MathJax-Element-25">g</script><code>.match(</code><span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-26-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-123" style="width: 0.533em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.436em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.44em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-124"><span class="mi" id="MathJax-Span-125" style="font-family: MathJax_Math-italic;">c</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 0.65em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>c</mi></math></span></span><script type="math/tex" id="MathJax-Element-26">c</script><code>)</code> returns a <code>MatchResult</code> object, <span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-27-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-126" style="width: 1.063em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.87em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.87em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-127"><span class="mi" id="MathJax-Span-128" style="font-family: MathJax_Math-italic;">m</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 0.65em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>m</mi></math></span></span><script type="math/tex" id="MathJax-Element-27">m</script>. If <span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-28-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-129" style="width: 1.063em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.87em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.87em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-130"><span class="mi" id="MathJax-Span-131" style="font-family: MathJax_Math-italic;">m</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 0.65em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>m</mi></math></span></span><script type="math/tex" id="MathJax-Element-28">m</script><code>.succeeded()</code> is true, <span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-29-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-132" style="width: 1.063em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.87em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.87em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-133"><span class="mi" id="MathJax-Span-134" style="font-family: MathJax_Math-italic;">m</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 0.65em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>m</mi></math></span></span><script type="math/tex" id="MathJax-Element-29">m</script> wraps a parse tree, and you can apply a semantics object to it. If <span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-30-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-135" style="width: 1.063em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.87em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.87em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-136"><span class="mi" id="MathJax-Span-137" style="font-family: MathJax_Math-italic;">m</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 0.65em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>m</mi></math></span></span><script type="math/tex" id="MathJax-Element-30">m</script><code>.failed()</code> is true, a detailed error message will be in <span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-31-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-138" style="width: 1.063em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.87em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.87em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-139"><span class="mi" id="MathJax-Span-140" style="font-family: MathJax_Math-italic;">m</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 0.65em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>m</mi></math></span></span><script type="math/tex" id="MathJax-Element-31">m</script><code>.message</code> and a smaller error message will be in <span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-32-Frame" tabindex="0" data-mathml="&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/math&gt;" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-141" style="width: 1.063em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.87em; height: 0px; font-size: 122%;"><span style="position: absolute; clip: rect(1.642em 1000.87em 2.365em -999.998em); top: -2.216em; left: 0em;"><span class="mrow" id="MathJax-Span-142"><span class="mi" id="MathJax-Span-143" style="font-family: MathJax_Math-italic;">m</span></span><span style="display: inline-block; width: 0px; height: 2.22em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.056em; border-left: 0px solid; width: 0px; height: 0.65em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>m</mi></math></span></span><script type="math/tex" id="MathJax-Element-32">m</script><code>.shortMessage</code>.

</li><li>You can add multiple semantics objects to grammar objects. A semantics is a collection of operations and attributes. Operations and attributes are applied to each node in the parse tree. Operations and attributes are similar: operations are functions (called every time), and attributes are memoized and called with property syntax. More on these when we get to more advanced uses.

</li><li>There are default things to do when a semantics object doesn’t have operations or attributes for all the rules. We’ll get to these cases as needed.
</li></ol>

<p>These notes are not exhaustive. There is much more to Ohm. Check out the <a href="https://github.com/harc/ohm/blob/master/doc/index.md">documentation</a>.</p>
      </div>
    </div>
    <script>
      var title = document.getElementsByTagName("h1")[0];
      if (title) document.title = title.innerHTML;
      var abstract = document.querySelector(".abstract");
      if (abstract) {
        var contentsDiv = document.createElement('div');
        contentsDiv.setAttribute('id', 'contents');
        var s = Array.from(document.getElementsByTagName("h2")).map(el => el.textContent);
        contentsDiv.innerHTML = '<div>CONTENTS</b></div><div>' + s.join(' • ') + '</div>';
        abstract.parentNode.insertBefore(contentsDiv, abstract.nextSibling);
      }
    </script>
  

<div style="position: absolute; width: 0px; height: 0px; overflow: hidden; padding: 0px; border: 0px; margin: 0px;"><div id="MathJax_Font_Test" style="position: absolute; visibility: hidden; top: 0px; left: 0px; width: auto; padding: 0px; border: 0px; margin: 0px; white-space: nowrap; text-align: left; text-indent: 0px; text-transform: none; line-height: normal; letter-spacing: normal; word-spacing: normal; font-size: 40px; font-weight: normal; font-style: normal; font-family: MathJax_Main, sans-serif;"></div></div></body></html>